/*
 * 计算 Jenks 自然断裂点法的矩阵
 *
 * 计算 Jenks 自然断裂点法所需的矩阵，这些矩阵可用于将数据分类到任意数量（classes <= nClasses）的类别中
 *
 * @私有方法
 */
function jenksMatrices(data, nClasses) {
    // 在原始实现中，这两个矩阵被称为 LC 和 OP：
    //
    // * lowerClassLimits (LC): 最优下界类别界限
    // * varianceCombinations (OP): 所有类别的最优方差组合
    const lowerClassLimits = [];
    const varianceCombinations = [];
    // 循环计数器
    let i;
    let j;
    // 计算过程中每一步的方差值
    let variance = 0;

    // 初始化并用零填充每个矩阵
    for (i = 0; i < data.length + 1; i++) {
        const tmp1 = [];
        const tmp2 = [];
        // 虽然这些数组初始值相同，但需要保持独立以避免相互影响
        for (j = 0; j < nClasses + 1; j++) {
            tmp1.push(0);
            tmp2.push(0);
        }
        lowerClassLimits.push(tmp1);
        varianceCombinations.push(tmp2);
    }

    for (i = 1; i < nClasses + 1; i++) {
        lowerClassLimits[1][i] = 1;
        varianceCombinations[1][i] = 0;
        // 原始实现使用 9999999，但 JavaScript 有 Infinity 故采用之
        for (j = 2; j < data.length + 1; j++) {
            varianceCombinations[j][i] = Number.POSITIVE_INFINITY;
        }
    }

    for (let l = 2; l < data.length + 1; l++) {
        // sum（原为SZ）：当前计算方差时的数值总和
        let sum = 0;
        // sumSquares（原为ZSQ）：当前数值的平方和
        let sumSquares = 0;
        // w（原为WT）：当前计算的数据点数量
        let w = 0;
        // i4（原为IV）：索引变量
        let i4 = 0;

        // 注意：虽然可用 Math.pow(x,2)，但直接相乘性能更优
        for (let m = 1; m < l + 1; m++) {
            // lowerClassLimit（原为III）：当前下界类别界限
            const lowerClassLimit = l - m + 1;
            const val = data[lowerClassLimit - 1];

            // 统计当前潜在分类的数据点
            w++;

            // 更新累加和与平方和
            sum += val;
            sumSquares += val * val;

            // 计算当前子序列的方差：平方和减去均值的平方乘以数量
            variance = sumSquares - (sum * sum) / w;

            i4 = lowerClassLimit - 1;

            if (i4 !== 0) {
                for (j = 2; j < nClasses + 1; j++) {
                    // 当添加新元素导致方差超过阈值时，在此位置进行类别划分
                    if (
                        varianceCombinations[l][j] >=
                        variance + varianceCombinations[i4][j - 1]
                    ) {
                        lowerClassLimits[l][j] = lowerClassLimit;
                        varianceCombinations[l][j] =
                            variance + varianceCombinations[i4][j - 1];
                    }
                }
            }
        }

        lowerClassLimits[l][1] = 1;
        varianceCombinations[l][1] = variance;
    }

    // 返回两个矩阵：lowerClassLimits 用于计算断裂点，varianceCombinations 用于评估拟合优度
    return {
        lowerClassLimits: lowerClassLimits,
        varianceCombinations: varianceCombinations
    };
}

export default jenksMatrices;
